package com.wmx.jdk8;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import org.junit.Test;

import java.util.*;
import java.util.function.ToIntFunction;
import java.util.stream.Collectors;

/**
 * java.util.Comparator 比较函数接口，通常用于自定义比较规则，比如 POJO、Map 对象等
 *
 * @author wangMaoXiong
 * @version 1.0
 * @date 2020/10/22 16:40
 */
public class ComparatorTest {

    /**
     * Collections.sort(List<T> list, Comparator<? super T> c) 根据指定的比较器引起的顺序对指定的列表进行排序。
     * <p>
     * java.util.Comparator 是一个函数式接口，需要实现 int compare(T o1, T o2) 方法
     * <p>
     * 1、比较两个参数（o1,o2）的顺序，当第一个参数小于、等于或大于第二个参数时，返回负整数、零或正整数
     * 2、compare 返回正整数，则认为o1大于o2，同时o1的值作为参数传递给下一次比较时的o2
     * 3、compare 返回负整数，则认为o1小于o2，同时o2的值作为参数传递给下一次比较时的o2
     * 4、下面演示顺序排列，null 值在最后面
     * 5、倒序也是同理，可以直接 反转列表中元素的顺序
     */
    @Test
    public void testCollectionsSort1() {
        // 随机造数据，其中包含 null 元素
        List<Map<String, Object>> data = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            Map<String, Object> map1 = new HashMap<>();
            int nextInt = new Random().nextInt(1000);
            map1.put("code", nextInt % 5 == 0 ? null : nextInt < 100 ? "0" + nextInt : nextInt + "");
            data.add(map1);
        }

        // [{code=754}, {code=431}, {code=232}, {code=null}, {code=null}, {code=277}, {code=116}, {code=632}, {code=null}, {code=154}]
        System.out.println(data);

        Collections.sort(data, new Comparator<Map<String, Object>>() {
            @Override
            public int compare(Map<String, Object> o1, Map<String, Object> o2) {
                Object code1 = o1.get("code");
                Object code2 = o2.get("code");
                if (code1 == null) {
                    // 返回-1，表示o2大；返回1，表示o1大
                    return code2 == null ? 0 : 1; // code1为null时，若code2也为null则相等；否则code1排后面
                }
                if (code2 == null) {
                    // 返回-1，表示o2大；返回1，表示o1大
                    return -1;// code2为null时，code1（非null）排前面
                }
                int i = Integer.parseInt(code1.toString()) - Integer.parseInt(code2.toString());
                return i;
            }
        });

        // [{code=116}, {code=154}, {code=232}, {code=277}, {code=431}, {code=632}, {code=754}, {code=null}, {code=null}, {code=null}]
        System.out.println(data);

        // 反转指定列表中元素的顺序
        Collections.reverse(data);

        // [{code=null}, {code=null}, {code=null}, {code=754}, {code=632}, {code=431}, {code=277}, {code=232}, {code=154}, {code=116}]
        System.out.println(data);
    }

    @Test
    public void testCollectionsSort2() {
        List<Map<String, Object>> dataList = new ArrayList<>();
        Map<String, Object> dataMpa1 = new HashMap<>();
        Map<String, Object> dataMpa2 = new HashMap<>();
        Map<String, Object> dataMpa3 = new HashMap<>();
        Map<String, Object> dataMpa4 = new HashMap<>();

        dataMpa1.put("create_time", DateUtil.parseDate("1993-10-23 12:00:02"));
        dataMpa2.put("create_time", DateUtil.parseDate("1893-10-23 12:00:02"));
        dataMpa3.put("create_time", null);
        dataMpa4.put("create_time", DateUtil.parseDate("2003-10-23 12:00:02"));

        dataList.add(dataMpa1);
        dataList.add(dataMpa2);
        dataList.add(dataMpa3);
        dataList.add(dataMpa4);

        // [{create_time=1993-10-23 00:00:00}, {create_time=1893-10-23 00:00:00}, {create_time=null}, {create_time=2003-10-23 00:00:00}]
        System.out.println(dataList);

        Collections.sort(dataList, new Comparator<Map<String, Object>>() {
            @Override
            public int compare(Map<String, Object> o1, Map<String, Object> o2) {
                Date create_time1 = (Date) o1.get("create_time");
                Date create_time2 = (Date) o2.get("create_time");
                if (create_time1 == null) {
                    // 返回1，表示o1大，null 往后排
                    return create_time2 == null ? 0 : 1;
                }
                if (create_time2 == null) {
                    // 返回-1，表示o2大，null 往后排
                    return -1;
                }
                // 乘以 -1，表示倒序排列.
                return -1 * create_time1.compareTo(create_time2);
            }
        });
        // [{create_time=2003-10-23 00:00:00}, {create_time=1993-10-23 00:00:00}, {create_time=1893-10-23 00:00:00}, {create_time=null}]
        System.out.println(dataList);
        // 反转指定列表中元素的顺序
        Collections.reverse(dataList);
        // [{create_time=null}, {create_time=1893-10-23 00:00:00}, {create_time=1993-10-23 00:00:00}, {create_time=2003-10-23 00:00:00}]
        System.out.println(dataList);
    }

    /**
     * 根据多个字段进行双重排序，多重排序，类似 sql 中的 order by code asc,name desc;
     * 演示效果：order by dept_no , emp_no desc
     */
    @Test
    public void testCollectionsSort3() {
        List<Map<String, Object>> empList = new ArrayList<>();
        Map<String, Object> dataMpa1 = new HashMap<>();
        Map<String, Object> dataMpa2 = new HashMap<>();
        Map<String, Object> dataMpa3 = new HashMap<>();
        Map<String, Object> dataMpa4 = new HashMap<>();

        dataMpa1.put("dept_no", "502025");
        dataMpa1.put("emp_no", "128");

        dataMpa2.put("dept_no", "302025");
        dataMpa2.put("emp_no", "229");

        dataMpa3.put("dept_no", "102025");
        dataMpa3.put("emp_no", "221");

        dataMpa4.put("dept_no", "302025");
        dataMpa4.put("emp_no", "321");

        empList.add(dataMpa1);
        empList.add(dataMpa2);
        empList.add(dataMpa3);
        empList.add(dataMpa4);

        // 排序前=[
        // {dept_no=502025, emp_no=128},
        // {dept_no=302025, emp_no=229},
        // {dept_no=102025, emp_no=221},
        // {dept_no=302025, emp_no=321}}
        System.out.println("排序前=" + empList);

        Collections.sort(empList, (o1, o2) -> {
            String deptNo1 = StrUtil.nullToEmpty(MapUtil.getStr(o1, "dept_no"));
            String empNo1 = StrUtil.nullToEmpty(MapUtil.getStr(o1, "emp_no"));
            String deptNo2 = StrUtil.nullToEmpty(MapUtil.getStr(o2, "dept_no"));
            String empNo2 = StrUtil.nullToEmpty(MapUtil.getStr(o2, "emp_no"));
            return StrUtil.equals(deptNo1, deptNo2) ? empNo1.compareTo(empNo2) : deptNo1.compareTo(deptNo2);
        });

        // 排序后=[
        // {dept_no=102025, emp_no=221},
        // {dept_no=302025, emp_no=229},
        // {dept_no=302025, emp_no=321},
        // {dept_no=502025, emp_no=128}]
        System.out.println("排序后=" + empList);
    }

    /**
     * 根据多个字段进行双重排序，多重排序，类似 sql 中的 order by code asc,name desc;
     * 演示效果：order by dept_no , create_time desc
     */
    @Test
    public void testCollectionsSort4() {
        List<Map<String, Object>> empList = new ArrayList<>();
        Map<String, Object> dataMpa1 = new HashMap<>();
        Map<String, Object> dataMpa2 = new HashMap<>();
        Map<String, Object> dataMpa3 = new HashMap<>();
        Map<String, Object> dataMpa4 = new HashMap<>();

        dataMpa1.put("dept_no", "502025");
        dataMpa1.put("emp_no", "128");
        dataMpa1.put("create_time", DateUtil.parseDate("1993-10-23 12:00:02"));

        dataMpa2.put("dept_no", "302025");
        dataMpa2.put("emp_no", "229");
        dataMpa2.put("create_time", DateUtil.parseDate("1999-10-23 12:00:02"));

        dataMpa3.put("dept_no", "102025");
        dataMpa3.put("emp_no", "221");
        dataMpa3.put("create_time", DateUtil.parseDate("1994-10-23 12:00:02"));

        dataMpa4.put("dept_no", "302025");
        dataMpa4.put("emp_no", "321");
        dataMpa4.put("create_time", DateUtil.parseDate("1996-10-23 12:00:02"));

        empList.add(dataMpa1);
        empList.add(dataMpa2);
        empList.add(dataMpa3);
        empList.add(dataMpa4);

        // 排序前=
        // [
        // {dept_no=502025, create_time=1993-10-23 00:00:00, emp_no=128},
        // {dept_no=302025, create_time=1999-10-23 00:00:00, emp_no=229},
        // {dept_no=102025, create_time=1994-10-23 00:00:00, emp_no=221},
        // {dept_no=302025, create_time=1996-10-23 00:00:00, emp_no=321}
        // ]
        System.out.println("排序前=" + empList);

        Collections.sort(empList, (o1, o2) -> {
            String deptNo1 = MapUtil.getStr(o1, "dept_no");
            Date createTime1 = MapUtil.getDate(o1, "create_time");
            String deptNo2 = MapUtil.getStr(o2, "dept_no");
            Date createTime2 = MapUtil.getDate(o2, "create_time");
            return StrUtil.equals(deptNo1, deptNo2) ? -1 * createTime1.compareTo(createTime2) : deptNo1.compareTo(deptNo2);
        });

        // 排序后=
        // [
        // {dept_no=102025, create_time=1994-10-23 00:00:00, emp_no=221},
        // {dept_no=302025, create_time=1999-10-23 00:00:00, emp_no=229},
        // {dept_no=302025, create_time=1996-10-23 00:00:00, emp_no=321},
        // {dept_no=502025, create_time=1993-10-23 00:00:00, emp_no=128}
        // ]
        System.out.println("排序后=" + empList);
    }

    /**
     * Arrays.sort(T[] a, Comparator<? super T> c) 根据指定的比较器引发的顺序对指定的对象数组进行排序。
     * <p>
     * java.util.Comparator 是一个函数式接口，需要实现 int compare(T o1, T o2) 方法
     * <p>
     * 1、比较两个参数（o1,o2）的顺序，当第一个参数小于、等于或大于第二个参数时，返回负整数、零或正整数
     * 2、compare 返回正整数，则认为o1大于o2，同时o1的值作为参数传递给下一次比较时的o2
     * 3、compare 返回负整数，则认为o1小于o2，同时o2的值作为参数传递给下一次比较时的o2
     */
    @Test
    public void arraySortTest() {
        // 随机造数据，其中包含 null 元素
        Map<String, Object>[] data = new Map[10];
        for (int i = 0; i < 10; i++) {
            Map<String, Object> map1 = new HashMap<>();
            int nextInt = new Random().nextInt(1000);
            map1.put("code", nextInt % 5 == 0 ? null : nextInt < 100 ? "0" + nextInt : nextInt + "");
            data[i] = map1;
        }

        //[{code=214}, {code=537}, {code=266}, {code=321}, {code=null}, {code=673}, {code=912}, {code=662}, {code=489}, {code=962}]
        System.out.println(Arrays.asList(data));

        // 顺序排序，null 元素在前
        Arrays.sort(data, (o1, o2) -> {
            Object code1 = o1.get("code");
            Object code2 = o2.get("code");
            if (code1 == null) {
                // 返回-1，表示o2大
                return code2 == null ? 0 : -1;
            }
            if (code2 == null) {
                // 返回-1，表示o1大
                return 1;
            }
            int i = Integer.parseInt(code1.toString()) - Integer.parseInt(code2.toString());
            return i;
        });

        //[{code=null}, {code=214}, {code=266}, {code=321}, {code=489}, {code=537}, {code=662}, {code=673}, {code=912}, {code=962}]
        System.out.println(Arrays.asList(data));
    }

    @Test
    public void sorted1() {
        Integer[] arr1 = {22, 23, 45, 5, 67, 678, 565, 4};
        // Comparator.reverseOrder()：返回一个与 自然排序相反的比较器。
        Arrays.sort(arr1, Comparator.reverseOrder());
        //[678, 565, 67, 45, 23, 22, 5, 4]
        System.out.println(Arrays.asList(arr1));
    }

    @Test
    public void sorted2() {
        Integer[] integers = {45, 56, 33, 4545, 233};
        List<Integer> list = Arrays.asList(integers);
        // Comparator.naturalOrder()：自然顺序
        Collections.sort(list, Comparator.naturalOrder());
        //[33, 45, 56, 233, 4545]
        System.out.println(list);
    }

    /**
     * Stream<T> sorted(Comparator<? super T> comparator) :排序操作
     * {@link Comparator} 用于比较的函数，naturalOrder 顺序排序，reverseOrder 倒序排序
     */
    @Test
    public void sorted3() {
        List<String> list = Arrays.asList("c", "e", "a", "d", "b");
        // 源列表：[c, e, a, d, b]
        System.out.println("源列表：" + list);

        List<String> collect1 = list.stream().sorted(Comparator.naturalOrder()).collect(Collectors.toList());
        // 顺序：[a, b, c, d, e]
        System.out.println("顺序：" + collect1);

        List<String> collect2 = list.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
        // 倒序：[e, d, c, b, a]
        System.out.println("倒序：" + collect2);
    }

    /**
     * Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor)：接受从类型 T中提取 int排序键的功能，并返回与该排序键进行比较的 Comparator<T>
     * 1、翻译过来就是：根据给定对象的某个属性进行排序，比如根据 POJO 的主键、年龄，或者 Map 中的某个属性等等，转为 int 类型进行比较
     * 2、注意因为要转为 int，所以值不能为 null，否则空指针异常
     * 3、参数 {@link ToIntFunction} 也是一个函数式接口，方法 int applyAsInt(T value) 用于类型转型
     * 4、其它的 comparingDouble、comparingLong 也是同理，不再赘述。
     */
    @Test
    public void sorted4() {
        // 随机造数据，其中包含 null 元素
        List<Map<String, Object>> data = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            Map<String, Object> map1 = new HashMap<>();
            int nextInt = new Random().nextInt(100);
            map1.put("id", i);
            map1.put("code", nextInt < 10 ? "0" + nextInt : nextInt + "");
            data.add(map1);
        }

        // 排序前：[{code=02, id=0}, {code=97, id=1}, {code=78, id=2}, {code=16, id=3}, {code=06, id=4}]
        System.out.println("排序前：" + data);

        // 根据 code 顺序排序
        List<Map<String, Object>> collect = data.stream().sorted(Comparator.comparingInt(new ToIntFunction<Map<String, Object>>() {
            @Override
            public int applyAsInt(Map<String, Object> value) {
                return Integer.parseInt(value.get("code").toString());
            }
        })).collect(Collectors.toList());

        // 排序后：[{code=02, id=0}, {code=06, id=4}, {code=16, id=3}, {code=78, id=2}, {code=97, id=1}]
        System.out.println("排序后：" + collect);
    }

    /**
     * nullsFirst(Comparator<? super T> comparator)：当比较的对象为 null 时，认为 null 小于非空值，则默认 null 排在前面。
     * nullsLast(Comparator<? super T> comparator) ：当比较的对象为 null 时，认为 null 大于非空值，则默认 null 排在后面。
     * 1、因为肯定会遇到这种情况，比如对 List<POJO> 根据 POJO 的某个属性进行排序，其中 POJO 会可能为 null，如果不加处理，则空指针异常
     */
    @Test
    public void sorted5() {
        // 随机造数据，其中包含 null 元素
        List<Map<String, Object>> data = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            Map<String, Object> map1 = new HashMap<>();
            int nextInt = new Random().nextInt(100);
            map1.put("id", i);
            map1.put("code", nextInt < 10 ? "0" + nextInt : nextInt + "");
            data.add(map1);
        }
        data.add(null);

        // 排序前：[{code=02, id=0}, {code=97, id=1}, {code=78, id=2}, {code=16, id=3}, {code=06, id=4}]
        System.out.println("排序前：" + data);

        // 根据 code 顺序排序
        List<Map<String, Object>> collect = data.stream()
                .sorted(Comparator.nullsFirst(Comparator.comparingInt(value -> Integer.parseInt(value.get("code").toString()))))
                .collect(Collectors.toList());

        // 排序后：[null, {code=19, id=3}, {code=62, id=4}, {code=68, id=2}, {code=72, id=1}, {code=98, id=0}]
        System.out.println("排序后：" + collect);
    }

    /**
     * comparing(Function<? super T,? extends U> keyExtractor)：接受从类型T中提取Comparable排序键的功能，并返回按该排序键进行比较的Comparator<T> 。
     * 1、类似上面的 comparingDouble、comparingLong、comparingInt，这三个的返回值是约定的 double、long、int 类型
     * 2、而 comparing 则是上面三个的通用写法，因为它的返回值可以自由值得任意类型
     */
    @Test
    public void sorted6() {
        // 随机造数据，其中包含 null 元素
        List<Map<String, Object>> data = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            Map<String, Object> map1 = new HashMap<>();
            int nextInt = new Random().nextInt(100);
            map1.put("id", i);
            map1.put("code", nextInt < 10 ? "0" + nextInt : nextInt + "");
            data.add(map1);
        }

        // 排序前：[{code=53, id=0}, {code=55, id=1}, {code=78, id=2}, {code=39, id=3}, {code=09, id=4}]
        System.out.println("排序前：" + data);

        // 根据 code 顺序排序
        List<Map<String, Object>> collect = data.stream()
                .sorted(Comparator.comparing(item -> Float.parseFloat(item.get("code").toString())))
                .collect(Collectors.toList());

        // 排序后：[{code=09, id=4}, {code=39, id=3}, {code=53, id=0}, {code=55, id=1}, {code=78, id=2}]
        System.out.println("排序后：" + collect);
    }

    /**
     * 对List<POJO> 中指定属性排序时，如果这个属性值可能为 null 呢？则可以使用如下方式，此时 map 的值是 Object 对象
     */
    @Test
    public void sorted7() {
        // 随机造数据，其中包含 null 元素
        List<Map<String, Object>> data = new ArrayList<>();
        data.add(null);
        for (int i = 0; i < 5; i++) {
            Map<String, Object> map1 = new HashMap<>();
            int nextInt = new Random().nextInt(100);
            map1.put("id", i);
            map1.put("code", nextInt % 4 == 0 ? null : nextInt < 10 ? "0" + nextInt : nextInt + "");
            data.add(map1);
        }

        // 排序前：[null, {code=02, id=0}, {code=57, id=1}, {code=05, id=2}, {code=73, id=3}, {code=35, id=4}]
        System.out.println("排序前：" + data);

        // 根据 code 顺序排序。nullsLast：对象为 null 时，排在最后
        List<Map<String, Object>> collect = data.stream()
                .sorted(Comparator.nullsLast(Comparator.comparing(item -> {
                    Object code = item.get("code");
                    if (code == null) {
                        // 正最大值，则表示 null 值排在末尾，相反，负正最大值， null 值排在最前
                        return Long.MAX_VALUE;
                    } else {
                        return Long.parseLong(code.toString());
                    }
                }))).collect(Collectors.toList());

        // 排序后：[{code=02, id=0}, {code=05, id=2}, {code=35, id=4}, {code=57, id=1}, {code=73, id=3}, null]
        System.out.println("排序后：" + collect);
    }

    @Test
    public void sorted8() {
        List<Map<String, Object>> dataList = new ArrayList<>();
        Map<String, Object> dataMpa1 = new HashMap<>();
        Map<String, Object> dataMpa2 = new HashMap<>();
        Map<String, Object> dataMpa3 = new HashMap<>();
        Map<String, Object> dataMpa4 = new HashMap<>();

        dataMpa1.put("create_time", DateUtil.parseDate("1993-10-23 12:00:02"));
        dataMpa2.put("create_time", DateUtil.parseDate("1893-10-23 12:00:02"));
        dataMpa3.put("create_time", null);
        dataMpa4.put("create_time", DateUtil.parseDate("2003-10-23 12:00:02"));

        dataList.add(dataMpa1);
        dataList.add(dataMpa2);
        dataList.add(null);
        dataList.add(dataMpa3);
        dataList.add(dataMpa4);

        // [{create_time=1993-10-23 00:00:00}, {create_time=1893-10-23 00:00:00}, null, {create_time=null}, {create_time=2003-10-23 00:00:00}]
        System.out.println("排序前：" + dataList);

        // 根据 create_time 倒序排序。nullsLast：对象为 null 时，排在最后
        List<Map<String, Object>> collect = dataList.stream()
                .sorted(Comparator.nullsLast(Comparator.comparing(item -> {
                    Date createTime = (Date) item.get("create_time");
                    if (createTime == null) {
                        // 最大值，表示 null 值排在末尾.
                        return Long.MAX_VALUE;
                    } else {
                        return -1 * createTime.getTime();
                    }
                }))).collect(Collectors.toList());

        // 排序后：[{create_time=2003-10-23 00:00:00}, {create_time=1993-10-23 00:00:00}, {create_time=1893-10-23 00:00:00}, {create_time=null}, null]
        System.out.println("排序后：" + collect);
    }

    /**
     * 如果没有 null 元素,则可以直接简写
     */
    @Test
    public void sorted9() {
        List<Map<String, Object>> ysbzDataList = new ArrayList<>();
        Map<String, Object> dataMpa1 = new HashMap<>();
        Map<String, Object> dataMpa2 = new HashMap<>();
        Map<String, Object> dataMpa3 = new HashMap<>();
        Map<String, Object> dataMpa4 = new HashMap<>();

        dataMpa1.put("create_time", DateUtil.parseDate("1993-10-23 12:00:02"));
        dataMpa2.put("create_time", DateUtil.parseDate("1893-10-23 12:00:02"));
        dataMpa3.put("create_time", DateUtil.parseDate("2013-10-23 12:00:02"));
        dataMpa4.put("create_time", DateUtil.parseDate("2003-10-23 12:00:02"));

        ysbzDataList.add(dataMpa1);
        ysbzDataList.add(dataMpa2);
        ysbzDataList.add(dataMpa3);
        ysbzDataList.add(dataMpa4);

        // 排序前：[{create_time=1993-10-23 00:00:00}, {create_time=1893-10-23 00:00:00}, {create_time=2013-10-23 00:00:00}, {create_time=2003-10-23 00:00:00}]
        System.out.println("排序前：" + ysbzDataList);

        // 根据 create_time 顺序排序
        ysbzDataList = ysbzDataList.stream().sorted(Comparator.comparing(item -> ((Date) item.get("create_time")))).collect(Collectors.toList());

        // 顺序排序：[{create_time=1893-10-23 00:00:00}, {create_time=2003-10-23 00:00:00}, {create_time=2013-10-23 00:00:00}, {create_time=1993-10-23 00:00:00}]
        System.out.println("顺序排序：" + ysbzDataList);

        // 反转指定列表中元素的顺序
        Collections.reverse(ysbzDataList);
        // 倒序排序：[{create_time=2013-10-23 00:00:00}, {create_time=2003-10-23 00:00:00}, {create_time=1993-10-23 00:00:00}, {create_time=1893-10-23 00:00:00}]
        System.out.println("倒序排序：" + ysbzDataList);
    }

    /**
     * <T, U> Comparator<T> comparing(Function<? super T, ? extends U> keyExtractor, Comparator<? super U> keyComparator)
     * 1、根据提取的key的值进行排序
     * 2、keyExtractor 用于提取排序的值，keyComparator 对前面提取的值进行排序。
     */
    @Test
    public void sorted10() {
        // 随机造数据，其中包含 null 元素
        List<Map<String, String>> agencyList = new ArrayList<>();

        Map<String, String> map1 = MapUtil.builder("id", "1").put("code", "001001").build();
        Map<String, String> map2 = MapUtil.builder("id", "2").put("code", "001").build();
        Map<String, String> map3 = MapUtil.builder("id", "3").put("code", "002").build();
        Map<String, String> map4 = MapUtil.builder("id", "4").put("code", null).build();
        Map<String, String> map5 = MapUtil.builder("id", "5").put("code", "002001").build();
        Map<String, String> map6 = MapUtil.builder("id", "3").put("code", "003").build();

        agencyList.add(map1);
        agencyList.add(map2);
        agencyList.add(map3);
        agencyList.add(map4);
        agencyList.add(map5);
        agencyList.add(map6);

        // 排序前：[{code=001001, id=1}, {code=001, id=2}, {code=002, id=3}, {code=null, id=4}, {code=002001, id=5}, {code=003, id=3}]
        System.out.println("排序前：" + agencyList);

        agencyList = agencyList.stream().sorted(Comparator.comparing(item ->
                                item.get("code") == null ? null : String.valueOf(item.get("code")),
                        Comparator.nullsLast(String::compareTo) // null值排在末尾，非null按字符串自然顺序升序
                ))
                .collect(Collectors.toList());

        // 顺序排序后：[{code=001, id=2}, {code=001001, id=1}, {code=002, id=3}, {code=002001, id=5}, {code=003, id=3}, {code=null, id=4}]
        System.out.println("顺序排序后：" + agencyList);
    }
}
